﻿using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Frames;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media;
using Action = Styx.TreeSharp.Action;


namespace PalaProt
{
    public partial class Main : CombatRoutine
    {
        public override string Name { get { return "Protection Paladin by Pasterke"; } }
        public override WoWClass Class { get { return WoWClass.Paladin; } }
        public LocalPlayer Me { get { return StyxWoW.Me; } }


        

        public string LastSpell = string.Empty;
        public override Composite CombatBehavior { get { return CreateCombat(); } }
        public override Composite PreCombatBuffBehavior { get { return CreatePreCombatBuffs(); } }
        public override Composite CombatBuffBehavior { get { return CreateCombatBuffs(); } }
        public override Composite PullBehavior { get { return CreatePull(); } }
        public override Composite RestBehavior { get { return CreateRest(); } }
        

        public bool isBoss { get { return IsWoWBoss(StyxWoW.Me.CurrentTarget); } }
        public bool Solo { get { return SoloOrNot(); } }
        public int addCount { get { return UnfriendlyUnits.Count(); } }
        public string usedBot { get { return BotManager.Current.Name.ToUpper(); } }
        private static bool shortPause = false;
        public bool PullSpell = false;


        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }


        public override void Initialize()
        {
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            EventHandlers.AttachCombatLogEvent();
            Updater.CheckForUpdate(UpdateSettingsPalaProt.myPrefs.Revision);
        }

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            EventHandlers.DetachCombatLogEvent();
        }

        #region pulse
        public override void Pulse()
        {
            try
            {
                if (Me.IsDead
                    && AutoBot)
                {
                    Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                }
                /*if (!Me.Combat && (usedBot.Contains("QUEST") || usedBot.Contains("GRIND")) && Lootables.Count() >= 1)
                {
                    GetLoot();
                }*/
                return;
            }
            catch { }
        }
        #endregion


        Composite CreateRest()
        {
            return new PrioritySelector(
                CastOnMe(FLASH_OF_LIGHT, ret => !Me.Combat
                    && CanBuffEat
                    && SpellManager.HasSpell(FLASH_OF_LIGHT) && (Me.HealthPercent > CRSettingsProt.myPrefs.FoodPercent && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentFlashOfLight)),
                new Decorator(ret => !Me.Combat && CanBuffEat, EatFood())
                );
        }


        Composite CreatePreCombatBuffs()
        {
            return new PrioritySelector(
                Cast(RIGHTEOUS_FURY, ret => CanBuffEat && !buffExists(RIGHTEOUS_FURY, Me) && CRSettingsProt.myPrefs.AutoRighteousFury),
                Blessing(),
                Seals()
                );
        }

        Composite CreateCombatBuffs()
        {
            return new PrioritySelector(
                Healthstone(),
                CastOnMe(SACRED_SHIELD, ret => gotTarget
                        && SpellManager.HasSpell(SACRED_SHIELD)
                        && !buffExists(SACRED_SHIELD_INT, Me)
                        && !spellOnCooldown(SACRED_SHIELD)),
                Cast(WORD_OF_GLORY, ret => gotTarget
                        && SpellManager.HasSpell(WORD_OF_GLORY)
                        && Me.GetCurrentPower(WoWPowerType.HolyPower) >= 3
                        && !spellOnCooldown(WORD_OF_GLORY)
                        && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentWordOfGlory),
                CastOnMe(ARDENT_DEFENDER, ret =>
                        SpellManager.HasSpell(ARDENT_DEFENDER)
                        && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentArdentDefender
                        && !spellOnCooldown(ARDENT_DEFENDER)),
                CastOnMe(GUARDIAN_OF_ANCIENT_KINGS, ret =>
                        SpellManager.HasSpell(GUARDIAN_OF_ANCIENT_KINGS)
                        && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentGuardianOfKings
                        && !spellOnCooldown(GUARDIAN_OF_ANCIENT_KINGS)),
                CastOnMe(LAY_ON_HANDS, ret =>
                        SpellManager.HasSpell(LAY_ON_HANDS)
                        && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentLayOnHands
                        && !spellOnCooldown(LAY_ON_HANDS)),
                CastOnMe(DIVINE_SHIELD, ret =>
                        SpellManager.HasSpell(DIVINE_SHIELD)
                        && !spellOnCooldown(DIVINE_SHIELD)
                        && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentDivineShield),
                CastOnMe(ETERNAL_FLAME, ret => gotTarget
                        && SpellManager.HasSpell(ETERNAL_FLAME)
                        && Me.GetCurrentPower(WoWPowerType.HolyPower) >= 3
                        && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentEternalFlame
                        && !buffExists(ETERNAL_FLAME, Me)),
                Cast("Barkskin", ret => gotTarget && SpellManager.HasSpell("Barkskin") && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentBarkskin),
                Cast(RIGHTEOUS_FURY, ret => !buffExists(RIGHTEOUS_FURY, Me) && CRSettingsProt.myPrefs.AutoRighteousFury),
                Blessing(),
                Seals()
                );
        }

		public Composite CreatePull()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                new Decorator(ret => gotTarget && !Me.CurrentTarget.IsWithinMeleeRange, CreateMovementBehavior()),
                Cast(AVENGERS_SHIELD, ret => gotTarget && !spellOnCooldown(AVENGERS_SHIELD) && Me.CurrentTarget.Distance <= 30),
                Cast(JUDGMENT, ret => gotTarget && !spellOnCooldown(JUDGMENT) && Me.CurrentTarget.Distance <= 30),
                Cast(CRUSADER_STRIKE, ret => gotTarget && !spellOnCooldown(CRUSADER_STRIKE) && Me.CurrentTarget.IsWithinMeleeRange)
                        
                );
        }

        Composite CreateCombat()
        {

            return new PrioritySelector(
				new Decorator(ret => Paused || (!AutoBot && Me.Mounted && Me.IsMoving), PauseCR()),
                new Decorator(ret => Me.CurrentTarget == null && AllowTargeting, FindTarget()),
                new Decorator(ret => Me.GotTarget
                    && AllowTargeting
                    && !Me.CurrentTarget.IsWithinMeleeRange
                    && MeleeAddCount >= 1, FindMeleeTarget()),
                new Decorator(ret => Me.CurrentTarget != null && (Me.CurrentTarget.IsDead || (AutoBot && Me.CurrentTarget.IsFriendly)), new Action(ret => { Me.ClearTarget(); return RunStatus.Failure; })),
               
                new Decorator(ret => gotTarget && AllowMovement && Me.CurrentTarget.Distance > myRange, CreateMovementBehavior()),
                new Decorator(ret => gotTarget && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget), FaceMyTarget()),
                new Decorator(ret => gotTarget && !Me.IsAutoAttacking, AutoAttack()),

                    Cast(HAMMER_OF_WRATH, ret => gotTarget
                        && SpellManager.HasSpell(HAMMER_OF_WRATH)
                        && !spellOnCooldown(HAMMER_OF_WRATH)
                        && Me.CurrentTarget.HealthPercent <= 20
                        && Me.CurrentTarget.Distance <= 30),

                    new Decorator(ret => CRSettingsProt.myPrefs.AutoInterrupt, InterruptTarget()),

                    StunningTarget(),

                    
                    Cast(CRUSADER_STRIKE, ret => gotTarget && !spellOnCooldown(CRUSADER_STRIKE) && !SpellManager.HasSpell(HAMMER_OF_THE_RIGHTEOUS)),
                    Cast(CRUSADER_STRIKE, ret => gotTarget && !spellOnCooldown(CRUSADER_STRIKE) && SpellManager.HasSpell(HAMMER_OF_THE_RIGHTEOUS) && addCount < 3),
                    Cast(JUDGMENT, ret => gotTarget && SpellManager.HasSpell(JUDGMENT) && !spellOnCooldown(JUDGMENT) && Me.CurrentTarget.Distance <= 30),
                    Cast(HAMMER_OF_THE_RIGHTEOUS, ret => gotTarget
                        && SpellManager.HasSpell(HAMMER_OF_THE_RIGHTEOUS)
                        && !spellOnCooldown(HAMMER_OF_THE_RIGHTEOUS)
                        && addCount >= 3 
                        && Me.CurrentTarget.IsWithinMeleeRange),
                    Cast(AVENGERS_SHIELD, ret => gotTarget 
                        && SpellManager.HasSpell(AVENGERS_SHIELD) 
                        && !spellOnCooldown(AVENGERS_SHIELD)),
                    Cast(SHIELD_OF_THE_RIGHTEOUS, ret => gotTarget
                        && SpellManager.HasSpell(SHIELD_OF_THE_RIGHTEOUS)
                        && Me.GetCurrentPower(WoWPowerType.HolyPower) >= 3),
                    Cast(CONSECRATION, ret => gotTarget 
                        && SpellManager.HasSpell(CONSECRATION)
                        && !spellOnCooldown(CONSECRATION) 
                        && Me.CurrentTarget.IsWithinMeleeRange),
                    Cast(AVENGING_WRATH, ret => gotTarget 
                        && isBoss 
                        && !spellOnCooldown(AVENGING_WRATH)
                        && Me.CurrentTarget.IsWithinMeleeRange),
                    Cast(HOLY_AVANGER, ret => gotTarget 
                        && isBoss 
                        && SpellManager.HasSpell(HOLY_AVANGER) 
                        && buffExists(AVENGING_WRATH, Me) 
                        && !spellOnCooldown(HOLY_AVANGER)
                        && Me.CurrentTarget.IsWithinMeleeRange),
                    Cast(EXECUTION_SENTENCE, ret => gotTarget
                        && SpellManager.HasSpell(EXECUTION_SENTENCE)
                        && !spellOnCooldown(EXECUTION_SENTENCE)
                        && Me.CurrentTarget.IsWithinMeleeRange),
                    Trinket1(),
                    Trinket2(),
                    DropCast(LIGHTS_HAMMER, ret => gotTarget 
                        && SpellManager.HasSpell(LIGHTS_HAMMER) 
                        && !spellOnCooldown(LIGHTS_HAMMER) 
                        && targetExistence(Me.CurrentTarget) >= 14
                        && Me.CurrentTarget.IsWithinMeleeRange),
                    Cast(HOLY_WRATH, ret => gotTarget 
                        && SpellManager.HasSpell(HOLY_WRATH) 
                        && !spellOnCooldown(HOLY_WRATH)
                        && addCount > 1
                        && Me.CurrentTarget.Distance <= 10)
                    
                    

                );
        }
        
        public string JUDGMENT = "Judgment";
        public string CRUSADER_STRIKE = "Crusader Strike";
        public string CONSECRATION = "Consecration";
        public string ETERNAL_FLAME = "Eternal Flame";
        public string WORD_OF_GLORY = "Word of Glory";
        public string SHIELD_OF_THE_RIGHTEOUS = "Shield of the Righteous";
        public string HAMMER_OF_THE_RIGHTEOUS = "Hammer of the Righteous";
        public string HAMMER_OF_WRATH = "Hammer of Wrath";
        public string EXECUTION_SENTENCE = "Execution Sentence";
        public string HOLY_WRATH = "Holy Wrath";
        public string HOLY_AVANGER = "Holy Avenger";
        public string AVENGERS_SHIELD = "Avenger's Shield";
        public string GUARDIAN_OF_ANCIENT_KINGS = "Guardian of Ancient Kings";
        public string DIVINE_SHIELD = "Divine Shield";
        public string LAY_ON_HANDS = "Lay on Hands";
        public string ARDENT_DEFENDER = "Ardent Defender";
        public string REBUKE = "Rebuke";
        public string FIST_OF_JUSTICE = "Fist of Justice";
        public string AVENGING_WRATH = "Avenging Wrath";
        public string DEVOTION_AURA = "Devotion Aura";
        public string RECKONING = "Reckoning";
        public string RIGHTEOUS_FURY = "Righteous Fury";
        public string FLASH_OF_LIGHT = "Flash of Light";
        public string LIGHTS_HAMMER = "Light's Hammer";
        public string SACRED_SHIELD = "Sacred Shield";
        public int SACRED_SHIELD_INT = 20925;

        #region CastDevotionAura
        WoWUnit UnitsCastingFear()
        {
            WoWUnit myTarget = ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => u != null
                && (u.IsCasting
                && (u.CastingSpell.ToString().Contains("Fear") || u.CastingSpell.ToString().Contains("Psychic Scream")))
                && !u.IsPet
                && !u.IsTotem
                && !u.IsFriendly
                && u.DistanceSqr <= 40 * 40)
                .FirstOrDefault();
            if (myTarget != null)
            {
                return myTarget;
            }
            return null;
        }
        Composite CastDevotionAura()
        {
            return new Decorator(ret => SpellManager.HasSpell(DEVOTION_AURA) && !spellOnCooldown(DEVOTION_AURA),
                new Action(ret =>
                {
                    WoWUnit fearCaster = UnitsCastingFear();
                    if (fearCaster != null && SpellManager.CanCast(DEVOTION_AURA))
                    {
                        SpellManager.Cast(DEVOTION_AURA);
                        Logging.Write(Colors.ForestGreen, "Detect Fear Casting, casting Devotion Aura");
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));
        }
        #endregion

        #region pullcast
        Composite PullCasting()
        {
            return new Action(ret =>
            {
                    if (SpellManager.HasSpell(AVENGERS_SHIELD) && !spellOnCooldown(AVENGERS_SHIELD) && SpellManager.CanCast(AVENGERS_SHIELD))
                    {
                        SpellManager.Cast(AVENGERS_SHIELD);
                        Logging.Write(Colors.LightBlue, AVENGERS_SHIELD);
                        PullSpell = true;
                        return RunStatus.Success;
                    }
                    if (SpellManager.HasSpell(RECKONING) && !spellOnCooldown(RECKONING) && SpellManager.CanCast(RECKONING))
                    {
                        SpellManager.Cast(RECKONING);
                        Logging.Write(Colors.LightBlue, RECKONING);
                        PullSpell = true;
                        return RunStatus.Success;
                    }
                    if (SpellManager.HasSpell(JUDGMENT) && !spellOnCooldown(JUDGMENT) && SpellManager.CanCast(JUDGMENT))
                    {
                        SpellManager.Cast(JUDGMENT);
                        Logging.Write(Colors.LightBlue, JUDGMENT);
                        PullSpell = true;
                        return RunStatus.Success;
                    }
                    if (SpellManager.HasSpell(CRUSADER_STRIKE) && !spellOnCooldown(CRUSADER_STRIKE) && SpellManager.CanCast(CRUSADER_STRIKE))
                    {
                        SpellManager.Cast(CRUSADER_STRIKE);
                        Logging.Write(Colors.LightBlue, CRUSADER_STRIKE);
                        return RunStatus.Success;
                    }
                    if (!Me.IsAutoAttacking && Me.CurrentTarget.IsWithinMeleeRange) 
                    { 
                        Lua.DoString("StartAttack()");
                        Logging.Write(Colors.LightBlue, "Auto Attack");
                        return RunStatus.Success;
                    }
                
                return RunStatus.Failure;
            });
        }
        
        #endregion

        #region AutoBot
        bool AutoBot
        {
            get
            {
                return usedBot.Contains("QUEST") || usedBot.Contains("GRIND") || usedBot.Contains("GATHER") || usedBot.Contains("ANGLER") || usedBot.Contains("ARCHEO");

            }
        }
        #endregion

        #region seals
        Composite Seals()
        {
            return new Action(ret =>
            {
                if (CanBuffEat
                    && !SpellManager.HasSpell("Seal of Truth")
                    && SpellManager.HasSpell("Seal of Command")
                    && !Me.HasAura("Seal of Command"))
                {
                    SpellManager.Cast("Seal of Command", Me);
                    Logging.Write(Colors.Pink, "Seal of Comand");
                    return RunStatus.Success;
                }
                if (CanBuffEat
                    && SpellManager.HasSpell("Seal of Truth")
                    && CRSettingsProt.myPrefs.WhatSealNeeded == CRSettingsProt.Seal.Truth
                    && !Me.HasAura("Seal of Truth"))
                {
                    SpellManager.Cast("Seal of Truth");
                    Logging.Write(Colors.Pink, "Seal of Truth");
                    return RunStatus.Success;
                }
                if (CanBuffEat
                    && SpellManager.HasSpell("Seal of Insight")
                    && CRSettingsProt.myPrefs.WhatSealNeeded == CRSettingsProt.Seal.Insight
                    && !Me.HasAura("Seal of Insight"))
                {
                    SpellManager.Cast("Seal of Insight");
                    Logging.Write(Colors.Pink, "Seal of Insight");
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region can buff and eat
        public bool CanBuffEat
        {
            get
            {
                return !Me.Mounted && !Me.IsFlying && !Me.OnTaxi && !Me.IsDead && !Me.IsGhost;
            }
        }
        #endregion

        #region overlayed
        public bool IsOverlayed(int spellID)
        {
            return Lua.GetReturnVal<bool>("return IsSpellOverlayed(" + spellID + ")", 0);
        }
        #endregion overlayed

        #region spellcharges
        public static double GetSpellCharges(int spellID)
        {
            return Lua.GetReturnVal<int>("return GetSpellCharges(" + spellID + ")", 0);
        }
        #endregion

        #region addcount
        IEnumerable<WoWUnit> UnfriendlyUnits
        {
            get
            {
                return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => u != null
                    && u.IsAlive
                    && (u.Combat && (u.IsTargetingMeOrPet || u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember))
                    && u.DistanceSqr <= 10 * 10);
            }
        }
        IEnumerable<WoWUnit> UnfriendlyMeleeUnits
        {
            get
            {
                return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => u != null
                    && u.IsAlive
                    && (u.Combat && (u.IsTargetingMeOrPet || u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember))
                    && u.Distance <= 8);
            }
        }
        public int MeleeAddCount
        {
            get { return UnfriendlyMeleeUnits.Count(); }
        }
        #endregion

        #region loot

        private double LootRange
        {
            get { return LootTargeting.LootRadius; }
        }
        private IOrderedEnumerable<WoWUnit> Lootables
        {
            get
            {
                var targetsList = ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(
                        p => p.Lootable && p.Distance <= LootRange).OrderBy(l => l.Distance);
                return targetsList;
            }
        }
        private void GetLoot()
        {
            if (Me.IsCasting || Lootables.Count() == 0 || Me.IsMoving)
                return;
            if (LootFrame.Instance != null && LootFrame.Instance.IsVisible)
            {
                LootFrame.Instance.LootAll();
                if (Me.CurrentTarget != null && Me.CurrentTarget.IsDead)
                {
                    Me.ClearTarget();
                }
                return;
            }
            var lootTarget = Lootables.FirstOrDefault();
            if (lootTarget.Distance > lootTarget.InteractRange && !Me.GroupInfo.IsInParty && !Me.GroupInfo.IsInRaid && !Me.IsInInstance)
            {
                Logging.Write("Moving to loot {0}.", lootTarget.Name);
                Navigator.MoveTo(lootTarget.Location);
            }
            else
            {
                lootTarget.Interact();
                if (Me.CurrentTarget != null && Me.CurrentTarget.IsDead)
                {
                    Me.ClearTarget();
                }
                return;
            }
        }
        #endregion loot

        #region FindTarget
        Composite FindTarget()
        {
            return new Decorator(ret => Me.CurrentTarget == null && AllowTargeting,
                new Action(ret =>
                {
                    WoWUnit myTarget = ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => ValidUnit(u)
                        && u.DistanceSqr <= 40 * 40
                        && !Blacklist.Contains(u, BlacklistFlags.All))
                        .OrderBy(u => u.Distance)
                        .FirstOrDefault();

                    if (myTarget != null)
                    {
                        myTarget.Target();
                        Logging.Write(Colors.PaleGreen, "Found new Target " + myTarget.Name);
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite FindMeleeTarget()
        {
            return
                new Action(ret =>
                {
                    WoWUnit myTarget = ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => u != null
                        && (u.Combat
                        && (u.IsTargetingMeOrPet || u.IsTargetingAnyMinion || u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember || u.IsTargetingPet))
                        && u.IsWithinMeleeRange
                        && !Blacklist.Contains(u, BlacklistFlags.All))
                        .OrderBy(u => u.Distance)
                        .FirstOrDefault();

                    if (myTarget != null)
                    {
                        myTarget.Target();
                        Logging.Write(Colors.PaleGreen, "Found new Target " + myTarget.Name);
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                });
        }
        #endregion

        #region crowdcontrol

        public bool IsCrowdControlledTarget(WoWUnit unit)
        {
            Dictionary<string, WoWAura>.ValueCollection auras = unit.Auras.Values;

            return unit.Fleeing
                || HasAuraWithEffect(unit,
                        WoWApplyAuraType.ModConfuse,
                        WoWApplyAuraType.ModCharm,
                        WoWApplyAuraType.ModFear,
                        WoWApplyAuraType.ModPossess);
        }

        public bool IsCrowdControlledPlayer(WoWUnit unit)
        {
            Dictionary<string, WoWAura>.ValueCollection auras = unit.Auras.Values;

            return unit.Rooted
                || unit.Fleeing
                || HasAuraWithEffect(unit,
                        WoWApplyAuraType.ModConfuse,
                        WoWApplyAuraType.ModCharm,
                        WoWApplyAuraType.ModFear,
                        WoWApplyAuraType.ModDecreaseSpeed,
                        WoWApplyAuraType.ModPacify,
                        WoWApplyAuraType.ModPacifySilence,
                        WoWApplyAuraType.ModPossess,
                        WoWApplyAuraType.ModRoot);
        }

        // this one optimized for single applytype lookup
        public bool HasAuraWithEffect(WoWUnit unit, WoWApplyAuraType applyType)
        {
            return unit.Auras.Values.Any(a => a.Spell != null && a.Spell.SpellEffects.Any(se => applyType == se.AuraType));
        }

        public static bool HasAuraWithEffect(WoWUnit unit, params WoWApplyAuraType[] applyType)
        {
            var hashes = new HashSet<WoWApplyAuraType>(applyType);
            return unit.Auras.Values.Any(a => a.Spell != null && a.Spell.SpellEffects.Any(se => hashes.Contains(se.AuraType)));
        }
        #endregion

        #region autoattack
        Composite AutoAttack()
        {
            return new Action(ret =>
            {
                Lua.DoString("StartAttack()");
                return RunStatus.Failure;
            });
        }
        #endregion

        #region paused pauseAoe
        Composite PauseCR()
        {
            return new Action(ret =>
            {
                return;
            });
        }
        #endregion

        #region spellcasting
        private delegate T Selection<out T>(object context);
        
        Composite Cast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        Logging.Write(Colors.Yellow, spell);
                        LastSpell = spell;
                        PullSpell = false;
                    }
                        ));
        }
        Composite DropCast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        SpellManager.ClickRemoteLocation(Me.Location);
                        Logging.Write(Colors.Yellow, spell);
                        LastSpell = spell;
                        PullSpell = false;
                    }
                        ));
        }
        Composite CastOnMe(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell, Me);
                        Logging.Write(Colors.Bisque, spell);
                        LastSpell = spell;
                    }
                        ));
        }
        public static TimeSpan GetSpellCooldown(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Original.CooldownTimeLeft;
            }


            return TimeSpan.MaxValue;
        }
        #endregion

        #region Kind of target
        public bool IsWoWBoss(WoWUnit mytarget)
        {
            if (StyxWoW.Me.CurrentTarget != null)
            {
                if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.WorldBoss)
                {
                    return true;
                }
                else if (target.IsBoss(mytarget))
                {
                    return true;
                }
                else if (Me.CurrentTarget.MaxHealth >= (100 * 1000000)) { return true; }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.RareElite
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * 3)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Rare
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * 3)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Elite
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * 3)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.Name.Contains("Dummy")
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.IsPlayer
                    && !StyxWoW.Me.CurrentTarget.IsFriendly)
                {
                    return true;
                }
            }
            return false;
        }
        #endregion Kind of Target

        #region pause
        public static bool PauseAoe = false;
        public static bool Paused = false;

        public static void HandleModifierStateChanged(object sender, LuaEventArgs args)
        {
            if (CRSettingsProt.myPrefs.StopCRKey == CRSettingsProt.Keypress.NONE
                && CRSettingsProt.myPrefs.StopAoeKey == CRSettingsProt.Keypress.NONE)
            {
                return;
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                string pauseMyAoe = "AOE cancelled, press " + CRSettingsProt.myPrefs.StopAoeKey.ToString() + " in WOW again to turn AOE back on";
                if (args.Args[0].ToString() == CRSettingsProt.myPrefs.StopAoeKey.ToString())
                {
                    PauseAoe = !PauseAoe;
                    if (PauseAoe)
                    {
                        Logging.Write("Aoe cancelled, press {0} in WOW again to resume Aoe",
                                     CRSettingsProt.myPrefs.StopAoeKey.ToString());
                        if (CRSettingsProt.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + pauseMyAoe + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Aoe Resumed");
                        if (CRSettingsProt.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Aoe Resumed !\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == CRSettingsProt.myPrefs.StopCRKey.ToString())
                {
                    string pauseCR = "CR paused, press " + CRSettingsProt.myPrefs.StopCRKey.ToString() + " in WOW again to turn back on";
                    Paused = !Paused;
                    if (Paused)
                    {
                        Logging.Write("CR paused, press {0} in WOW again to turn back on",
                                     CRSettingsProt.myPrefs.StopCRKey.ToString());
                        if (CRSettingsProt.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + pauseCR + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("CR running again ....");
                        if (CRSettingsProt.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"CR running again ....\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
        }
        #endregion pause

        #region solo or not
        public bool SoloOrNot()
        {
            return (!StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                && !StyxWoW.Me.GroupInfo.IsInRaid
                && !StyxWoW.Me.IsInInstance;
        }
        #endregion

		#region movement targeting facing
        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        public bool AllowFacing
        {
            get
            {
                if (CRSettingsProt.myPrefs.DisableAutoFacing
                    && (Me.GroupInfo.IsInRaid || Me.IsInInstance || Me.GroupInfo.PartyMembers.Count() >= 3))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }
                return CRSettingsProt.myPrefs.AutoFacing;

            }
        }
        public bool AllowTargeting
        {
            get
            {
                if (CRSettingsProt.myPrefs.DisableAutoTargeting
                    && (Me.GroupInfo.IsInRaid || Me.IsInInstance || Me.GroupInfo.PartyMembers.Count() > 3))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }
                return CRSettingsProt.myPrefs.AutoTargeting;
            }
        }
        public bool AllowMovement
        {
            get
            {
                if (CRSettingsProt.myPrefs.DisableAutoMovement
                    && (Me.GroupInfo.IsInRaid || Me.IsInInstance || Me.GroupInfo.PartyMembers.Count() > 3))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }


                return CRSettingsProt.myPrefs.AutoMovement;
            }
        }

        Composite CreateMovementBehavior()
        {
            return
                    new Action(ret =>
                    {
                        if (gotTarget && !Me.CurrentTarget.InLineOfSight)
                        {
                            Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                        }
                        if (gotTarget && !Me.CurrentTarget.IsWithinMeleeRange)
                        {
                            Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                        }
                        if (gotTarget && Me.CurrentTarget.IsWithinMeleeRange)
                        {
                            Navigator.PlayerMover.MoveStop();
                        }
                        return RunStatus.Failure;
                    }
                );
        }
        
        Composite CreateMoveBackBehavior()
        {
            return new Action(ret =>
            {
                WoWMovement.Move(WoWMovement.MovementDirection.Backwards);
                while (gotTarget && Me.CurrentTarget.IsAlive && Me.CurrentTarget.Distance < 10)
                {
                    break;
                }
                Navigator.PlayerMover.MoveStop();
                return RunStatus.Failure;
            });
        }
        float myRange
        {
            get
            {
                if (IsWoWBoss(Me.CurrentTarget)) { return 4.5f; }
                if (Me.CurrentTarget.IsPlayer) { return 1.5f; }
                return 3.5f;
            }
        }
        public bool NeedGoBackwards
        {
            get
            {
                return Me.CurrentTarget != null && (Me.CurrentTarget.IsCasting && Me.CurrentTarget.CastingSpell.ToString() == "Blazing Cleave");
            }
        }
        #endregion

        #region facing
        Composite FaceMyTarget()
        {
            return
                new Action(ret =>
                {
                    Me.CurrentTarget.Face();
                    return RunStatus.Failure;
                });
        }
        #endregion

        #region valid units
        public bool ValidUnit(WoWUnit p)
        {
            if (p == null || !p.IsValid)
                return false;

            // Ignore shit we can't select
            if (!p.CanSelect)
            {
                return false;
            }

            // Ignore shit we can't attack
            if (!p.Attackable)
            {
                return false;
            }

            // Duh
            if (p.IsDead)
            {
                return false;
            }

            // check for enemy players here as friendly only seems to work on npc's
            if (p.IsPlayer)
            {
                WoWPlayer pp = p.ToPlayer();
                if (pp.IsHorde == StyxWoW.Me.IsHorde)
                {
                    return false;
                }

                if (pp.Guid == StyxWoW.Me.CurrentTargetGuid && CanAttackCurrentTarget)
                {
                    return false;
                }

                return true;
            }

            // Ignore friendlies!
            if (p.IsFriendly)
            {
                return false;
            }
            // If it is a pet/minion/totem, lets find the root of ownership chain
            WoWPlayer pOwner = GetPlayerParent(p);

            // ignore if owner is player, alive, and not blacklisted then ignore (since killing owner kills it)
            // .. following .IsMe check to prevent treating quest mob summoned by us that we need to kill as invalid 
            if (pOwner != null && pOwner.IsAlive && !pOwner.IsMe)
            {
                if (!ValidUnit(pOwner))
                {
                    return false;
                }
                if (!Blacklist.Contains(pOwner, BlacklistFlags.Combat))
                {
                    return false;
                }
                if (!StyxWoW.Me.IsPvPFlagged)
                {
                    return false;
                }
            }

            // And ignore critters (except for those ferocious ones) /non-combat pets
            if (p.IsNonCombatPet)
            {
                return false;
            }

            // And ignore critters (except for those ferocious ones) /non-combat pets
            if (p.IsCritter && p.ThreatInfo.ThreatValue == 0 && !p.IsTargetingMyRaidMember)
            {
                return false;
            }
            /*
                        if (p.CreatedByUnitGuid != 0 || p.SummonedByUnitGuid != 0)
                            return false;
            */
            return true;
        }

        public WoWPlayer GetPlayerParent(WoWUnit unit)
        {
            // If it is a pet/minion/totem, lets find the root of ownership chain
            WoWUnit pOwner = unit;
            while (true)
            {
                if (pOwner.OwnedByUnit != null)
                    pOwner = pOwner.OwnedByRoot;
                else if (pOwner.CreatedByUnit != null)
                    pOwner = pOwner.CreatedByUnit;
                else if (pOwner.SummonedByUnit != null)
                    pOwner = pOwner.SummonedByUnit;
                else
                    break;
            }

            if (unit != pOwner && pOwner.IsPlayer)
                return pOwner as WoWPlayer;

            return null;
        }
        public bool CanAttackCurrentTarget
        {
            get
            {
                if (StyxWoW.Me.CurrentTarget == null)
                    return false;

                return Lua.GetReturnVal<bool>("return UnitCanAttack(\"player\",\"target\")", 0);
            }
        }
        #endregion

        #region eatfood
        Composite EatFood()
        {
            return new Decorator(ret => Me.HealthPercent <= CRSettingsProt.myPrefs.FoodPercent && CanBuffEat && !Me.IsSwimming && !Me.GroupInfo.IsInRaid && !Me.IsInInstance,
                new Action(ret =>
                {
                    Styx.CommonBot.Rest.Feed();
                    return RunStatus.Failure;
                }));
        }
        #endregion

        #region CanInterrupt

        WoWUnit InterruptableUnits()
        {
            WoWUnit myTarget = ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => u != null
                && u.InLineOfSight
                && (u.IsCasting
                && Me.CanInterruptCurrentSpellCast)
                && !u.IsPet
                && !u.IsTotem
                && !u.IsFriendly
                && u.IsWithinMeleeRange)
                .OrderBy(u => u.IsPlayer)
                .ThenBy(u => u.Distance)
                .FirstOrDefault();
            if (myTarget != null)
            {
                return myTarget;
            }
            return null;
        }
        WoWUnit NonInterruptableUnits()
        {
            WoWUnit myTarget = ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => u != null
                && u.InLineOfSight
                && (u.IsCasting
                && !Me.CanInterruptCurrentSpellCast)
                && !u.IsPet
                && !u.IsTotem
                && !u.IsFriendly
                && u.IsWithinMeleeRange)
                .OrderBy(u => u.IsPlayer)
                .ThenBy(u => u.Distance)
                .FirstOrDefault();
            if (myTarget != null)
            {
                return myTarget;
            }
            return null;
        }
        public Composite InterruptTarget()
        {
            return new Action(ret =>
            {
                var unit = InterruptableUnits();

                if (unit != null)
                {
                    if (SpellManager.HasSpell("Rebuke") 
                        && !spellOnCooldown("Rebuke") 
                        && SpellManager.CanCast("Rebuke")
                        && unit.IsWithinMeleeRange
                        && LastSpell != "War Stomp"
                        && LastSpell != "Hammer of Justice"
                        && LastSpell != "Fist of Justice")
                    {
                        SpellManager.Cast("Rebuke", unit);
                        Logging.Write(Colors.Yellow, "Interrupting " + unit.Name + " with Rebuke");
                        LastSpell = "Rebuke";
                        return RunStatus.Success;
                    }
                    if (SpellManager.HasSpell("War Stomp") && !spellOnCooldown("War Stomp") && SpellManager.CanCast("War Stomp") && unit.IsWithinMeleeRange)
                    {
                        SpellManager.Cast("War Stomp", unit);
                        Logging.Write(Colors.Yellow, "Interrupting " + unit.Name + " with War Stomp");
                        LastSpell = "War Stomp";
                        return RunStatus.Success;
                    }
                    if (unit != null
                        && SpellManager.HasSpell("Fist of Justice")
                        && !spellOnCooldown("Fist of Justice")
                        && SpellManager.CanCast("Fist of Justice")
                        && LastSpell != "Rebuke"
                        && LastSpell != "War Stomp")
                    {
                        SpellManager.Cast("Fist of Justice", unit);
                        Logging.Write(Colors.Yellow, "Stunning " + unit.Name + " with Fist of Justice");
                        LastSpell = "Fist of Justice";
                        return RunStatus.Success;
                    }
                    if (unit != null
                        && !SpellManager.HasSpell("Fist of Justice")
                        && SpellManager.HasSpell("Hammer of Justice")
                        && !spellOnCooldown("Hammer of Justice")
                        && SpellManager.CanCast("Hammer of Justice")
                        && LastSpell != "Rebuke"
                        && LastSpell != "War Stomp")
                    {
                        SpellManager.Cast("Hammer of Justice", unit);
                        Logging.Write(Colors.Yellow, "Stunning " + unit.Name + " with Hammer of Justice");
                        LastSpell = "Hammer of Justice";
                        return RunStatus.Success;
                    }
                }
                return RunStatus.Failure;
            }

                );
        }
        Composite StunningTarget()
        {
            return new Decorator(
                new Action(ret =>
                {

                    var unit = NonInterruptableUnits();

                    if (unit != null
                        && SpellManager.HasSpell("War Stomp")
                        && !spellOnCooldown("War Stomp")
                        && SpellManager.CanCast("War Stomp")
                        && unit.IsWithinMeleeRange
                        && LastSpell != "Hammer of Justice"
                        && LastSpell != "Fist of Justice")
                    {
                        SpellManager.Cast("War Stomp", unit);
                        Logging.Write(Colors.Red, "Stunning " + unit.Name + " with War Stomp");
                        LastSpell = "War Stomp";
                        return RunStatus.Success;
                    }
                    if (unit != null
                        && SpellManager.HasSpell("Fist of Justice")
                        && !spellOnCooldown("Fist of Justice")
                        && SpellManager.CanCast("Fist of Justice")
                        && LastSpell != "War Stomp")
                    {
                        SpellManager.Cast("Fist of Justice", unit);
                        Logging.Write(Colors.Yellow, "Stunning " + unit.Name + " with Fist of Justice");
                        LastSpell = "Fist of Justice";
                        return RunStatus.Success;
                    }
                    if (unit != null
                        && !SpellManager.HasSpell("Fist of Justice")
                        && SpellManager.HasSpell("Hammer of Justice")
                        && !spellOnCooldown("Hammer of Justice")
                        && SpellManager.CanCast("Hammer of Justice")
                        && LastSpell != "War Stomp")
                    {
                        SpellManager.Cast("Hammer of Justice", unit);
                        Logging.Write(Colors.Yellow, "Stunning " + unit.Name + " with Hammer of Justice");
                        LastSpell = "Hammer of Justice";
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));

        }
        #endregion

        #region Res tanks - healers

        public static List<WoWPlayer> Tanks
        {
            get
            {
                if (!StyxWoW.Me.GroupInfo.IsInParty)
                    return new List<WoWPlayer>(); ;

                return StyxWoW.Me.GroupInfo.RaidMembers.Where(p => p.HasRole(WoWPartyMember.GroupRole.Tank))
                    .Select(p => p.ToPlayer())
                    .Union(new[] { RaFHelper.Leader })
                    .Where(p => p != null && p.IsDead)
                    .Distinct()
                    .ToList();
            }
        }

        public static List<WoWPlayer> Healers
        {
            get
            {
                if (!StyxWoW.Me.GroupInfo.IsInParty)
                    return new List<WoWPlayer>(); ;

                return StyxWoW.Me.GroupInfo.RaidMembers.Where(p => p.HasRole(WoWPartyMember.GroupRole.Healer))
                    .Select(p => p.ToPlayer()).Where(p => p != null && p.IsDead).ToList();

            }
        }
        public static bool AnyTankNearby
        {
            get
            {
                return Tanks.Any(h => h.IsDead && h.Distance < 40);
            }
        }
        public static bool AnyHealerNearby
        {
            get
            {
                return Healers.Any(h => h.IsDead && h.Distance < 40);
            }
        }
        Composite ResTank()
        {
            return new Decorator(ret => SpellManager.HasSpell("Rebirth") && CRSettingsProt.myPrefs.AutoResTank && AnyTankNearby,
                new Action(ret =>
                {
                    var ResTankTarget = Tanks.FirstOrDefault();
                    if (ResTankTarget != null && ResTankTarget.InLineOfSight)
                    {
                        SpellManager.Cast("Rebirth", ResTankTarget);
                        Logging.Write(Colors.Orange, "Ressing Tank" + ResTankTarget);
                        Lua.DoString("SendChatMessage(\"Resssing Tank\"" + ResTankTarget + ");");
                    }
                    return RunStatus.Failure;

                }));
        }
        Composite ResHealer()
        {
            return new Decorator(ret => SpellManager.HasSpell("Rebirth") && CRSettingsProt.myPrefs.AutoResHealer && AnyHealerNearby,
                new Action(ret =>
                {
                    var ResHealTarget = Healers.FirstOrDefault();
                    if (ResHealTarget != null && ResHealTarget.InLineOfSight)
                    {
                        SpellManager.Cast("Rebirth", ResHealTarget);
                        Logging.Write(Colors.Orange, "Ressing Healer" + ResHealTarget);
                        string message = "Ressing " + ResHealTarget;
                        Lua.DoString("SendChatMessage(\"Resssing Healer \"" + ResHealTarget + ");");
                    }
                    return RunStatus.Failure;
                }));
        }
        #endregion

        #region useitems
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }

        Composite Trinket1()
        {
            return
                new Decorator(ret => gotTarget && Me.Combat && CRSettingsProt.myPrefs.AutoTrinket1 && (Me.CurrentTarget != null && Me.CurrentTarget.IsWithinMeleeRange),
                    new Action(ret =>
                    {
                        var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
                        if (CRSettingsProt.myPrefs.trinket1Manapercent > 0
                            && Me.ManaPercent <= CRSettingsProt.myPrefs.trinket1Manapercent
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsProt.myPrefs.trinket1hppercent > 0
                            && Me.HealthPercent <= CRSettingsProt.myPrefs.trinket1hppercent
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsProt.myPrefs.trinket1crowdcontrolled
                            && IsCrowdControlledPlayer(Me)
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsProt.myPrefs.trinket1dpsboost
                            && IsWoWBoss(Me.CurrentTarget)
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        return RunStatus.Failure;
                    }));
        }
        Composite Trinket2()
        {
            return
                new Decorator(ret => gotTarget && Me.Combat && CRSettingsProt.myPrefs.AutoTrinket2 && (Me.CurrentTarget != null && Me.CurrentTarget.IsWithinMeleeRange),
                    new Action(ret =>
                    {
                        var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;

                        if (CRSettingsProt.myPrefs.trinket2hppercent > 0
                            && Me.ManaPercent <= CRSettingsProt.myPrefs.trinket2Manapercent
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsProt.myPrefs.trinket2hppercent > 0
                            && Me.HealthPercent <= CRSettingsProt.myPrefs.trinket2hppercent
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsProt.myPrefs.trinket2crowdcontrolled
                            && IsCrowdControlledPlayer(Me)
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsProt.myPrefs.trinket2dpsboost
                            && IsWoWBoss(Me.CurrentTarget)
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        return RunStatus.Failure;
                    }));
        }
        Composite Healthstone()
        {
            return new Decorator(ret => Me.Combat && Me.HealthPercent <= CRSettingsProt.myPrefs.PercentHealthstone,
                new Action(ret =>
                {
                    var hstone = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 5512);
                    if (hstone != null && hstone.Usable)
                    {
                        hstone.Use();
                        Logging.Write("Using Healthstone");
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite AlchemyFlask()
        {
            return new Decorator(
                new Action(ret =>
                {
                    var alchflask = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 75525);
                    if (alchflask != null && alchflask.Usable && alchflask.Cooldown <= 0)
                    {
                        alchflask.Use();
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite CrystalOfInsanity()
        {
            return new Action(ret =>
            {
                var crystal = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 86569);
                if (crystal != null && crystal.Usable && crystal.Cooldown <= 0)
                {
                    crystal.Use();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region blessings

        Composite Blessing()
        {
            return new Action(ret =>
            {
                if (CanBuffEat
                    && CRSettingsProt.myPrefs.WhatBlessingNeeded == CRSettingsProt.Blessings.Auto)
                {
                    if(!SpellManager.HasSpell("Blessing of Might"))
                    {
                        if (!buffExists("Blessing of Kings", Me)
                            && !buffExists("Mark of the Wild", Me)
                            && !buffExists("Legacy of the Emperor", Me)
                            && !buffExists("Embrace of the Shale Spider", Me)
                            && LastSpell != "Blessing of Kings")
                        {
                            SpellManager.Cast("Blessing of Kings", Me);
                            Logging.Write(Colors.Aquamarine, "Blessing of Kings");
                            LastSpell = "Blessing of Kings";
                            return RunStatus.Success;
                        }
                    }
                    if (CanBuffEat
                        && SpellManager.HasSpell("Blessing of Kings") && SpellManager.HasSpell("Blessing of Might"))
                    {
                        if (!buffExists("Blessing of Kings", Me)
                            && !buffExists("Mark of the Wild", Me)
                            && !buffExists("Legacy of the Emperor", Me)
                            && !buffExists("Embrace of the Shale Spider", Me)
                            && !buffExists("Blessing of Forgotten Kings", Me)
                            && LastSpell != "Blessing of Kings")
                        {
                            SpellManager.Cast("Blessing of Kings", Me);
                            Logging.Write(Colors.Aquamarine, "Auto Blessing of Kings");
                            LastSpell = "Blessing of Kings";
                            return RunStatus.Success;
                        }
                        if (CanBuffEat
                            && !buffExists("Blessing of Might", Me)
                            && !buffExists("Grace of Air", Me)
                            && !buffExists("Roar of Courage", Me)
                            && !buffExists("Spirit Beast Blessing", Me)
                            && (buffExists("Mark of the Wild", Me)
                            || buffExists("Legacy of the Emperor", Me)
                            || buffExists("Embrace of the Shale Spider", Me)
                            || buffExists("Blessing of Forgotten Kings", Me))
                            && LastSpell != "Blessing of Might")
                        {
                            if (SpellManager.CanCast("Blessing of Might"))
                            {
                                SpellManager.Cast("Blessing of Might", Me);
                                Logging.Write(Colors.Aquamarine, "Auto Blessing of Might");
                                LastSpell = "Blessing of Might";
                                return RunStatus.Success;
                            }
                        }
                    }
                }
                if (CanBuffEat
                    && SpellManager.HasSpell("Blessing of Kings")
                    && !Me.HasAura("Blessing of Kings")
                    && !buffExists("Mark of the Wild", Me)
                    && !buffExists("Legacy of the Emperor", Me)
                    && !buffExists("Embrace of the Shale Spider", Me)
                    && !buffExists("Blessing of Forgotten Kings", Me)
                    && CRSettingsProt.myPrefs.WhatBlessingNeeded == CRSettingsProt.Blessings.Kings)
                {
                    if (SpellManager.CanCast("Blessing of Kings"))
                    {
                        SpellManager.Cast("Blessing of Kings", Me);
                        Logging.Write(Colors.Aquamarine, "Blessing of Kings");
                        LastSpell = "Blessing of Kings";
                        return RunStatus.Success;
                    }
                }
                if (CanBuffEat
                    && SpellManager.HasSpell("Blessing of Might")
                    && !Me.HasAura("Blessing of Might")
                    && CRSettingsProt.myPrefs.WhatBlessingNeeded == CRSettingsProt.Blessings.Might)
                {
                    if (SpellManager.CanCast("Blessing of Might"))
                    {
                        SpellManager.Cast("Blessing of Might", Me);
                        Logging.Write(Colors.Aquamarine, "Blessing of Might");
                        LastSpell = "Blessing of Might";
                        return RunStatus.Success;
                    }
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region Timers
        private static System.Timers.Timer pauseTimer;
        public static void ShortPause(int ms)
        {
            shortPause = true;
            pauseTimer = new System.Timers.Timer(ms);
            pauseTimer.Elapsed += new System.Timers.ElapsedEventHandler(delegate
            {
                shortPause = false;
            });
            pauseTimer.Enabled = true;
            pauseTimer.AutoReset = false;
        }
        #endregion
    }
}
